package com.eudon.ai.agent.config;

import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeChatProperties;
import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeConnectionProperties;
import com.alibaba.cloud.ai.autoconfigure.dashscope.ResolvedConnectionProperties;
import com.alibaba.cloud.ai.dashscope.api.DashScopeApi;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions;
import io.micrometer.observation.ObservationRegistry;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.observation.ChatModelObservationConvention;
import org.springframework.ai.model.function.FunctionCallback;
import org.springframework.ai.model.function.FunctionCallbackResolver;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestClient;
import org.springframework.web.reactive.function.client.WebClient;

import java.util.List;

import static com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeConnectionUtils.resolveConnectionProperties;

/**
 * @author eudon
 * @description 自定义ChatModel
 * @date 2025/8/16
 * @email syd19970616@gmail.com
 * @address <a href="https://gitee.com/eudon">Gitee</a>
 */
@Configuration
@Slf4j
public class MyDashscopeChatModelAutoConfiguration {

    @Bean("qwenTurbo")
    public ChatModel qwenTurbo(MyDashscopeChatModelDTO dto) {
        return this.dashscopeChatModel(dto, new MyChatOptions(true, 0.8, "qwen-turbo"));
    }

    private ChatModel dashscopeChatModel(MyDashscopeChatModelDTO dto, MyChatOptions options) {
        var dashscopeApi = dashscopeChatApi(dto);
        DashScopeChatOptions chatOptions = DashScopeChatOptions.builder()
                .withEnableSearch(options.enableSearch)
                .withTemperature(options.temperature)
                .withModel(options.modelName)
                .build();

        var dashscopeModel = new DashScopeChatModel(
                dashscopeApi,
                chatOptions,
                dto.functionCallbackResolver,
                dto.toolFunctionCallbacks,
                dto.retryTemplate,
                dto.observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP)
        );

        dto.observationConvention.ifAvailable(dashscopeModel::setObservationConvention);

        return dashscopeModel;
    }

    private DashScopeApi dashscopeChatApi(MyDashscopeChatModelDTO dto) {

        ResolvedConnectionProperties resolved = resolveConnectionProperties(
                dto.commonProperties,
                dto.chatProperties,
                "chat"
        );

        return new DashScopeApi(
                resolved.baseUrl(),
                resolved.apiKey(),
                resolved.workspaceId(),
                dto.restClientBuilder,
                dto.webClientBuilder,
                dto.responseErrorHandler
        );
    }

    @Getter
    @Component
    public static class MyDashscopeChatModelDTO {

        private final DashScopeConnectionProperties commonProperties;

        private final DashScopeChatProperties chatProperties;

        private final RestClient.Builder restClientBuilder;

        private final WebClient.Builder webClientBuilder;

        private final List<FunctionCallback> toolFunctionCallbacks;

        private final FunctionCallbackResolver functionCallbackResolver;

        private final RetryTemplate retryTemplate;

        private final ResponseErrorHandler responseErrorHandler;

        private final ObjectProvider<ObservationRegistry> observationRegistry;

        private final ObjectProvider<ChatModelObservationConvention> observationConvention;

        public MyDashscopeChatModelDTO(DashScopeConnectionProperties commonProperties, DashScopeChatProperties chatProperties, RestClient.Builder restClientBuilder, WebClient.Builder webClientBuilder, List<FunctionCallback> toolFunctionCallbacks, FunctionCallbackResolver functionCallbackResolver, RetryTemplate retryTemplate, ResponseErrorHandler responseErrorHandler, ObjectProvider<ObservationRegistry> observationRegistry, ObjectProvider<ChatModelObservationConvention> observationConvention) {
            this.commonProperties = commonProperties;
            this.chatProperties = chatProperties;
            this.restClientBuilder = restClientBuilder;
            this.webClientBuilder = webClientBuilder;
            this.toolFunctionCallbacks = toolFunctionCallbacks;
            this.functionCallbackResolver = functionCallbackResolver;
            this.retryTemplate = retryTemplate;
            this.responseErrorHandler = responseErrorHandler;
            this.observationRegistry = observationRegistry;
            this.observationConvention = observationConvention;
        }
    }

    private record MyChatOptions(boolean enableSearch, double temperature, String modelName) {
    }
}
